package com.xuecheng.base.exception;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.ArrayList;
import java.util.List;

/**
 * 全局异常处理器
 */
//- @ExceptionHandler
//- Spring3.0提供的标识在方法上或类上的注解，用来表明方法的处理异常类型。
//- @ControllerAdvice
//- Spring3.2提供的新注解，从名字上可以看出大体意思是控制器增强，
//- 在项目中来增强SpringMVC中的Controller。通常和@ExceptionHandler 结合使用，来处理SpringMVC的异常信息。
//- @ResponseStatus
//- Spring3.0提供的标识在方法上或类上的注解，用状态代码和应返回的原因标记方法或异常类。
//- 参数是想要处理的http错误状态代码 比如: @ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR) value可以省略
//调用处理程序方法时，状态代码将应用于HTTP响应。

@ControllerAdvice
@Slf4j
@ResponseBody //返回json数据
public class GlobalExceptionHandler {

    //处理自定义异常
    @ExceptionHandler(XuechengPlusException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse customException(XuechengPlusException e) {
        //获取错误信息
        String errMessage = e.getErrMessage();
        log.error("【异常信息】{}",errMessage,e);
        return new RestErrorResponse(errMessage);
    }

    //处理非自定义异常
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse exception(Exception e) {
        //获取错误信息
        String errMessage = CommonError.UNKNOWN_ERROR.getErrMessage();
        if (e.getMessage() != null) {
            errMessage = e.getMessage();
        }
        log.error("【异常信息】{}",errMessage,e);
        return new RestErrorResponse(errMessage);
    }

    //处理使用JSR 303注解校验时抛出的异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse exception(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        List<String> msgList = new ArrayList<>();
        //将错误信息放在msgList
        bindingResult.getFieldErrors().stream().forEach(item->msgList.add(item.getDefaultMessage()));
        //拼接错误信息
        String msg = StringUtils.join(msgList, ",");
        log.error("【系统异常】{}",msg);
        return new RestErrorResponse(msg);
    }
}
